<template>
  <div class="dashboard">
    <div class="dashboard-header">
      <h1>数据可视化大屏</h1>
      <div class="controls">
        <el-dropdown @command="handleTemplateCommand">
          <el-button type="primary">
            布局模板
            <i class="el-icon-arrow-down el-icon--right"></i>
          </el-button>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item command="template1">
              模板一 (2x2)
            </el-dropdown-item>
            <el-dropdown-item command="template2">
              模板二 (3x2)
            </el-dropdown-item>
            <el-dropdown-item command="template3">
              模板三 (1+3)
            </el-dropdown-item>
            <el-dropdown-item command="saveAsTemplate">
              保存当前布局为模板
            </el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
        <button @click="addWidget">添加图表</button>
        <button @click="saveLayout">保存布局</button>
      </div>
    </div>

    <grid-layout
      :layout="computedLayout"
      @update:layout="updateLayout"
      :col-num="12"
      :row-height="30"
      :is-draggable="true"
      :is-resizable="true"
      :vertical-compact="true"
      :margin="[10, 10]"
      :use-css-transforms="true"
      class="layout"
    >
      <grid-item
        v-for="item in computedLayout"
        :key="item.i"
        :x="item.x"
        :y="item.y"
        :w="item.w"
        :h="item.h"
        :i="item.i"
        class="grid-item"
      >
        <component
          :is="item.component"
          :chart-data="item.data"
          :chart-options="item.options"
        />
        <div class="widget-controls">
          <button @click="removeWidget(item.i)">删除</button>
        </div>
      </grid-item>
    </grid-layout>

    <!-- 添加图表的弹窗 -->
    <el-dialog
      :title="dialogTitle"
      :visible.sync="dialogVisible"
      :close-on-click-modal="false"
    >
      <template v-if="!selectedChartType">
        <div class="chart-types">
          <el-button @click="selectChartType('line')">折线图</el-button>
          <el-button @click="selectChartType('pie')">饼图</el-button>
          <el-button @click="selectChartType('bar')">柱状图</el-button>
          <el-button @click="selectChartType('table')">表格</el-button>
        </div>
      </template>

      <template v-else>
        <data-source-config
          :chart-type="selectedChartType"
          :current-config="currentDataConfig"
          @submit="handleDataConfigSubmit"
          @cancel="handleDataConfigCancel"
        />
      </template>
    </el-dialog>
  </div>
</template>

<script>
import { GridLayout, GridItem } from 'vue-grid-layout'
import { mapState, mapMutations } from 'vuex'
import LineChart from '../components/ChartComponents/LineChart.vue'
import PieChart from '../components/ChartComponents/PieChart.vue'
import BarChart from '../components/ChartComponents/BarChart.vue'
import DataTable from '../components/ChartComponents/DataTable.vue'
import DataSourceConfig from '../components/DataSourceConfig.vue'

export default {
  name: 'Dashboard',
  components: {
    GridLayout,
    GridItem,
    LineChart,
    PieChart,
    BarChart,
    DataTable,
    DataSourceConfig,
  },
  data() {
    return {
      dialogVisible: false,
      currentLayout: [],
      templates: {
        template1: [
          {
            x: 0,
            y: 0,
            w: 6,
            h: 8,
            i: 't1-1',
            component: 'LineChart',
            data: {},
          },
          {
            x: 6,
            y: 0,
            w: 6,
            h: 8,
            i: 't1-2',
            component: 'PieChart',
            data: {},
          },
          {
            x: 0,
            y: 8,
            w: 6,
            h: 8,
            i: 't1-3',
            component: 'BarChart',
            data: {},
          },
          {
            x: 6,
            y: 8,
            w: 6,
            h: 8,
            i: 't1-4',
            component: 'DataTable',
            data: {},
          },
        ],
        template2: [
          {
            x: 0,
            y: 0,
            w: 4,
            h: 8,
            i: 't2-1',
            component: 'LineChart',
            data: {},
          },
          {
            x: 4,
            y: 0,
            w: 4,
            h: 8,
            i: 't2-2',
            component: 'PieChart',
            data: {},
          },
          {
            x: 8,
            y: 0,
            w: 4,
            h: 8,
            i: 't2-3',
            component: 'BarChart',
            data: {},
          },
          {
            x: 0,
            y: 8,
            w: 6,
            h: 8,
            i: 't2-4',
            component: 'DataTable',
            data: {},
          },
          {
            x: 6,
            y: 8,
            w: 6,
            h: 8,
            i: 't2-5',
            component: 'LineChart',
            data: {},
          },
        ],
        template3: [
          {
            x: 0,
            y: 0,
            w: 12,
            h: 8,
            i: 't3-1',
            component: 'LineChart',
            data: {},
          },
          {
            x: 0,
            y: 8,
            w: 4,
            h: 8,
            i: 't3-2',
            component: 'PieChart',
            data: {},
          },
          {
            x: 4,
            y: 8,
            w: 4,
            h: 8,
            i: 't3-3',
            component: 'BarChart',
            data: {},
          },
          {
            x: 8,
            y: 8,
            w: 4,
            h: 8,
            i: 't3-4',
            component: 'DataTable',
            data: {},
          },
        ],
      },
      selectedChartType: null,
      currentDataConfig: null,
    }
  },
  computed: {
    ...mapState(['layout']),
    computedLayout: {
      get() {
        return this.layout || []
      },
      set(newLayout) {
        this.UPDATE_LAYOUT(newLayout)
      },
    },
    dialogTitle() {
      return this.selectedChartType ? '配置数据源' : '添加图表'
    },
  },
  created() {
    // 确保初始布局是一个数组
    if (!Array.isArray(this.layout)) {
      this.UPDATE_LAYOUT([])
    }
  },
  mounted() {
    if (this.layout.length === 0) {
      const savedLayout = localStorage.getItem('dashboard-layout')
      if (savedLayout) {
        try {
          const parsedLayout = JSON.parse(savedLayout)
          if (Array.isArray(parsedLayout)) {
            this.UPDATE_LAYOUT(parsedLayout)
          }
        } catch (e) {
          console.error('Error parsing saved layout:', e)
        }
      }
    }

    // 加载保存的模板
    const savedTemplates = localStorage.getItem('dashboard-templates')
    if (savedTemplates) {
      try {
        this.templates = { ...this.templates, ...JSON.parse(savedTemplates) }
      } catch (e) {
        console.error('Error loading templates:', e)
      }
    }
  },
  methods: {
    ...mapMutations(['UPDATE_LAYOUT', 'ADD_WIDGET', 'REMOVE_WIDGET']),

    updateLayout(newLayout) {
      if (Array.isArray(newLayout)) {
        this.UPDATE_LAYOUT(newLayout)
      }
    },

    addWidget() {
      this.dialogVisible = true
    },

    selectChartType(type) {
      this.selectedChartType = type
    },

    handleDataConfigSubmit(config) {
      // 创建新的图表组件
      const widget = {
        x: (this.computedLayout.length * 2) % 12,
        y: 0,
        w: 6,
        h: 8,
        i: Date.now().toString(),
        component: this.getComponentName(this.selectedChartType),
        data: {},
        options: {},
        dataConfig: config, // 保存数据源配置
      }

      this.ADD_WIDGET(widget)
      this.dialogVisible = false
      this.selectedChartType = null

      // 立即加载数据
      this.loadWidgetData(widget)
    },

    handleDataConfigCancel() {
      this.selectedChartType = null
    },

    getComponentName(type) {
      const componentMap = {
        line: 'LineChart',
        pie: 'PieChart',
        bar: 'BarChart',
        table: 'DataTable',
      }
      return componentMap[type]
    },

    async loadWidgetData(widget) {
      if (!widget.dataConfig?.sourceId) return

      try {
        // 检查是否是默认数据源
        if (widget.dataConfig.sourceId.startsWith('default-')) {
          // 生成模拟数据
          const mockData = this.generateMockData(widget.dataConfig)
          widget.data = this.transformData(
            mockData,
            widget.component,
            widget.dataConfig
          )
        } else {
          // 调用实际的API
          const response = await fetch(
            `/api/data/${widget.dataConfig.sourceId}`,
            {
              method: 'POST',
              headers: {
                'Content-Type': 'application/json',
              },
              body: JSON.stringify(widget.dataConfig),
            }
          )

          const data = await response.json()
          widget.data = this.transformData(
            data,
            widget.component,
            widget.dataConfig
          )
        }

        // 设置自动刷新
        if (widget.dataConfig.autoRefresh) {
          if (widget.refreshTimer) {
            clearInterval(widget.refreshTimer)
          }
          widget.refreshTimer = setInterval(() => {
            this.loadWidgetData(widget)
          }, widget.dataConfig.refreshInterval * 1000)
        }
      } catch (error) {
        console.error('Failed to load widget data:', error)
        this.$message.error('加载数据失败')
      }
    },

    transformData(data, chartType, config) {
      switch (chartType) {
        case 'LineChart':
        case 'BarChart':
          return {
            title: {
              text: config.sourceId.startsWith('default-1')
                ? '销售数据'
                : '访问统计',
              textStyle: {
                color: '#fff',
              },
            },
            tooltip: {
              trigger: 'axis',
            },
            xAxis: {
              type: 'category',
              data: data.map((item) => item[config.xField]),
              axisLine: { lineStyle: { color: '#fff' } },
              axisLabel: { color: '#fff' },
            },
            yAxis: {
              type: 'value',
              axisLine: { lineStyle: { color: '#fff' } },
              axisLabel: { color: '#fff' },
            },
            series: [
              {
                data: data.map((item) => item[config.yField]),
                type: chartType === 'LineChart' ? 'line' : 'bar',
                itemStyle: {
                  color: chartType === 'LineChart' ? '#409EFF' : '#67C23A',
                },
              },
            ],
          }
        case 'PieChart':
          return {
            title: {
              text: config.sourceId.startsWith('default-1')
                ? '销售分布'
                : '访问来源',
              textStyle: { color: '#fff' },
            },
            tooltip: {
              trigger: 'item',
              formatter: '{a} <br/>{b}: {c} ({d}%)',
            },
            legend: {
              orient: 'horizontal',
              bottom: 10,
              textStyle: { color: '#fff' },
            },
            series: [
              {
                name: config.sourceId.startsWith('default-1')
                  ? '销售额'
                  : '访问量',
                type: 'pie',
                radius: ['40%', '70%'],
                avoidLabelOverlap: false,
                itemStyle: {
                  borderRadius: 10,
                  borderColor: '#fff',
                  borderWidth: 2,
                },
                label: {
                  show: true,
                  color: '#fff',
                },
                emphasis: {
                  label: {
                    show: true,
                    fontSize: '20',
                    fontWeight: 'bold',
                  },
                },
                data: data.map((item) => ({
                  name: item[config.categoryField],
                  value: item[config.yField],
                })),
              },
            ],
          }
        case 'DataTable':
          return {
            columns: config.fields.map((field) => ({
              prop: field,
              label: this.getFieldLabel(field),
              width: 'auto',
            })),
            data: data,
          }
        default:
          return data
      }
    },

    getFieldLabel(fieldName) {
      // 这里可以维护一个字段名称映射表
      return fieldName
    },

    removeWidget(id) {
      this.REMOVE_WIDGET(id)
    },

    saveLayout() {
      if (Array.isArray(this.layout)) {
        localStorage.setItem('dashboard-layout', JSON.stringify(this.layout))
      }
    },

    handleTemplateCommand(command) {
      if (command === 'saveAsTemplate') {
        this.saveAsTemplate()
      } else {
        this.applyTemplate(command)
      }
    },

    applyTemplate(templateName) {
      const template = this.templates[templateName]
      if (template) {
        // 为每个组件生成新的唯一ID
        const newLayout = template.map((item) => ({
          ...item,
          i: Date.now() + '-' + Math.random().toString(36).substr(2, 9),
          data: this.getDefaultData(
            item.component.toLowerCase().replace('chart', '')
          ),
        }))
        this.UPDATE_LAYOUT(newLayout)
        this.saveLayout()
      }
    },

    // 添加生成模拟数据的方法
    generateMockData(config) {
      const data = []
      const now = new Date()

      // 生成30条模拟数据
      for (let i = 0; i < 30; i++) {
        const item = {}

        // 根据数据源类型生成不同的数据
        if (config.sourceId === 'default-1') {
          item.date = new Date(now - i * 24 * 3600 * 1000)
            .toISOString()
            .split('T')[0]
          item.sales = Math.floor(Math.random() * 10000)
          item.category = ['服装', '电子', '食品', '家居'][
            Math.floor(Math.random() * 4)
          ]
          item.region = ['华东', '华南', '华北', '西部'][
            Math.floor(Math.random() * 4)
          ]
          item.profit = Math.floor(item.sales * (0.1 + Math.random() * 0.2))
        } else if (config.sourceId === 'default-2') {
          item.time = new Date(now - i * 3600 * 1000).toISOString()
          item.pv = Math.floor(Math.random() * 1000)
          item.uv = Math.floor(item.pv * (0.3 + Math.random() * 0.4))
          item.source = ['直接访问', '搜索引擎', '社交媒体', '外部链接'][
            Math.floor(Math.random() * 4)
          ]
          item.bounce = Math.random() * 0.5
        }

        data.push(item)
      }

      return data
    },
  },
  watch: {
    // 监听布局变化
    layout: {
      handler(newLayout) {
        if (Array.isArray(newLayout)) {
          this.saveLayout()
        }
      },
      deep: true,
    },
  },
  beforeDestroy() {
    // 清理所有定时器
    this.computedLayout.forEach((widget) => {
      if (widget.refreshTimer) {
        clearInterval(widget.refreshTimer)
      }
    })
  },
}
</script>


<style scoped>
.dashboard {
  background: url('../../../../assets/dashboard-bg.png') center center;
  background-size: cover;
  background-size: 100% 100%;
}

.dashboard {
  padding: 20px;
}

.dashboard-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.controls {
  display: flex;
  gap: 10px;
}

.widget-controls {
  position: absolute;
  top: 5px;
  right: 5px;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.3s;
}

.grid-item:hover .widget-controls {
  opacity: 1;
}

.chart-types {
  display: flex;
  gap: 10px;
  justify-content: center;
  padding: 20px;
}

.layout {
  min-height: calc(100vh - 100px);
  background: transparent;
  position: relative;
}

.grid-item {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 4px;
  overflow: hidden;
  backdrop-filter: blur(10px);
}

/* 美化按钮样式 */
button {
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: #fff;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
}

button:hover {
  background: rgba(255, 255, 255, 0.2);
}

.el-dropdown {
  margin-right: 10px;
}

.template-preview {
  width: 200px;
  height: 120px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  margin-bottom: 10px;
  background: rgba(0, 0, 0, 0.2);
}

.el-dropdown {
  margin-right: 10px;
}

.template-preview {
  width: 200px;
  height: 120px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  margin-bottom: 10px;
  background: rgba(0, 0, 0, 0.2);
}

/* 移除之前的 button 样式，改用 element-ui 的按钮样式 */
.el-button {
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid rgba(255, 255, 255, 0.7);
  color: #999;
}

.el-button:hover {
  background: rgba(255, 255, 255, 0.5);
  border-color: rgba(255, 255, 255, 0.8);
  color: #999;
}
</style> 